// DBInterfaceMySQL.h
// DBMySQL
// MySQL Database driver for the Protea Project / Provides interface to MySQL
// Copyright (C) 2003, 2004, 2005 eXegeSys, Inc.
// Copyright (C) 2008 Bruce A. James
//
// This program is part of the Protea Project.
//
// The Protea Project is free software; you can redistribute it and/or modify it 
// under the terms of the GNU General Public License as published by the 
// Free Software Foundation, either version 3 of the License, or (at your 
// option) any later version.
//
// The Protea Project is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
// for more details.
// 
// You should have received a copy of the GNU General Public License along 
// with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// Please send correspondence to:
//
// theproteaproject@gmail.com
//

#ifndef __PROTEA_DBINTERFACEMYSQL_H__
#define __PROTEA_DBINTERFACEMYSQL_H__

#include "../DBInterface.h"
#include "../prepSQL.h"
#include "../../Buffer/Buffer.h"
#include "../../Fields/fields.h"
#include "../../Appdic/appdic.h"

XCDBDriverDescr* descriptor;

// Global functions
extern "C" {
	__EXPORT db_type XCRegisteredDBI();
	__EXPORT XCDBInterface* MakeInterface( XCDBHandlerConnection* p, XCAppInterface* app );
	__EXPORT XCDBDriverDescr* GetDBDescriptor() { return descriptor; };
};

class XCDBConnectionMySQL;

// Database Interface Class
class __EXPORT XCDBInterfaceMySQL : public XCDBInterface
{
	friend class XCDBStatementMySQL;
	friend class XCDBConnectionMySQL;

public:
	// Constructor
	XCDBInterfaceMySQL( XCDBHandlerConnection* p, XCAppInterface* app );
	~XCDBInterfaceMySQL();

	// Supported by all drivers
	///////////////////////////
	XCDBConnection* Connect( const char* uid, const char* pass );

	// Optionally supported by drivers
	//////////////////////////////////
	void CreateDB( char* name, XCDBTransaction* txn );
	bool RenameTable( char* result, char* source, char* dest );
	void OpenExclusive();
	void UserInfo();
	XCDBDriverDescr* GetDatabaseInfo();

private:
	// MySQL environment
	MYSQL environment;
};



// Connection class
class __EXPORT XCDBConnectionMySQL : public XCDBConnection
{
	friend class XCDBTransactionMySQL;
	friend class XCDBStatementMySQL;
	friend class XCDBInterfaceMySQL;
	friend class XCSQLStatementMySQL;

public:
	// Disconnects this connection
	void Disconnect();

	// Creates a new transaction object
	XCDBTransaction* CreateTxn();

	// Refreshes the connection
	bool Refresh();

private:
	XCDBConnectionMySQL( XCDBInterfaceMySQL* dbint );
	void Connect( const char* uid, const char* pass, const char* database );

	XCDBInterfaceMySQL*	hDB;	// Pointer to SQL connection

	// MySQL connection handle
	MYSQL* conn;
};



// Transaction class
class __EXPORT XCDBTransactionMySQL : public XCDBTransaction
{
	friend class XCDBInterfaceMySQL;
	friend class XCDBStatementMySQL;

public:
	XCDBTransactionMySQL( XCDBConnectionMySQL* i, XCDBInterfaceMySQL* dbint );
	~XCDBTransactionMySQL();

	void Begin( isolevel il = serializable );
	void Commit();
	void Rollback();
	void Prepare();
	XCDBStatement* CreateStmt( XCBuffer* buf );
	XCDBStatement* CreateStmt2( XCSQLGen* SQLGen );

	void LockTable( XCBuffer* table, XCField* value );

	long GetDatabaseNumber();

private:
	XCDBInterfaceMySQL*	hDB;	// Pointer to connection
	XCDBConnectionMySQL*	hConn;	// Pointer to SQL connection
	long dbnumber;						// Database number
};


class __EXPORT XCSQLStatementMySQL : public XCSQLStatement
{
	friend class XCDBInterfaceMySQL;
	friend class XCDBStatementMySQL;
public:
	// we need our own constructor
	XCSQLStatementMySQL( XCDBConnectionMySQL* connection );
	XCSQLStatementMySQL( XCDBConnectionMySQL* connection, XCSQLGen *query );

	//put functions we need to overwrite here.
	int GetValue(XCField* fld, char* start = NULL);
	int GetDataType( XCField* fld, char* start, bool& do_not_null );

private:
	XCDBConnectionMySQL*	hConn;	// Pointer to SQL connection
};




class __EXPORT XCDBStatementMySQL : public XCDBStatement
{
	friend class XCDBInterfaceMySQL;
	friend class XCDBTransactionMySQL;

public:
	XCDBStatementMySQL( XCDBInterfaceMySQL* dbi, XCDBTransactionMySQL* txn, XCBuffer* buf );
	XCDBStatementMySQL( XCDBInterfaceMySQL* dbi, XCDBTransactionMySQL* txn, XCSQLGen* query );
	virtual ~XCDBStatementMySQL();

	bool MakeStmt();
	bool Execute( char* sqlstr );
	bool Execute();
	void MoveNext();
	bool Eof() { return IsEof; };
	char* GetSQLString() { return stmt->sql_data; };	// will return string that is executed (with ?s and all)
	char* GetSQLString( char* buffer );	// this one will return a string with parameters filled in
	void Release();

private:
	XCBuffer*						pBuf;
	XCDBConnectionMySQL*		hConn;
	XCDBTransactionMySQL*		hTxn;
	XCDBInterfaceMySQL*		hDB;

	bool IsASelect;
	bool IsEof;		// EOF flag

	XCSQLStatementMySQL* stmt;

	// MySQL results handle
	MYSQL_RES* results;
	MYSQL_ROW row;

	XCField** fields;
	unsigned int field_count;
};

#endif

